
/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "SampleCode.h"
#include "SkView.h"
#include "SkCanvas.h"
#include "SkDevice.h"
#include "SkPaint.h"
#include "SkShader.h"

static SkBitmap createBitmap(int n)
    {
    SkBitmap bitmap;
    bitmap.setConfig(SkBitmap::kARGB_8888_Config, n, n);
    bitmap.allocPixels();
    bitmap.eraseColor(0);

    SkCanvas canvas(bitmap);
    SkRect r;
    r.set(0, 0, SkIntToScalar(n), SkIntToScalar(n));
    SkPaint paint;
    paint.setAntiAlias(true);

    paint.setColor(SK_ColorRED);
    canvas.drawOval(r, paint);
    paint.setColor(SK_ColorBLUE);
    paint.setStrokeWidth(SkIntToScalar(n)/15);
    paint.setStyle(SkPaint::kStroke_Style);
    canvas.drawLine(0, 0, r.fRight, r.fBottom, paint);
    canvas.drawLine(0, r.fBottom, r.fRight, 0, paint);

    return bitmap;
    }

class MipMapView : public SampleView
    {
        SkBitmap fBitmap;
        enum
            {
            N = 64
            };
    public:
        MipMapView()
            {
            fBitmap = createBitmap(N);

            fWidth = N;
            }

    protected:
        // overrides from SkEventSink
        virtual bool onQuery(SkEvent* evt)
            {
            if (SampleCode::TitleQ(*evt))
                {
                SampleCode::TitleR(evt, "MipMaps");
                return true;
                }
            return this->INHERITED::onQuery(evt);
            }

        void drawN(SkCanvas* canvas, const SkBitmap& bitmap)
            {
            SkAutoCanvasRestore acr(canvas, true);
            for (int i = N; i > 1; i >>= 1)
                {
                canvas->drawBitmap(bitmap, 0, 0, NULL);
                canvas->translate(SkIntToScalar(N + 8), 0);
                canvas->scale(SK_ScalarHalf, SK_ScalarHalf);
                }
            }

        void drawN2(SkCanvas* canvas, const SkBitmap& bitmap)
            {
            SkBitmap bg;
            bg.setConfig(SkBitmap::kARGB_8888_Config, N, N);
            bg.allocPixels();

            SkAutoCanvasRestore acr(canvas, true);
            for (int i = 0; i < 6; i++)
                {
                bg.eraseColor(0);
                SkCanvas c(bg);
                c.scale(SK_Scalar1 / (1 << i), SK_Scalar1 / (1 << i));
                c.drawBitmap(bitmap, 0, 0, NULL);

                canvas->save();
                canvas->scale(SkIntToScalar(1 << i), SkIntToScalar(1 << i));
                canvas->drawBitmap(bg, 0, 0, NULL);
                canvas->restore();
                canvas->translate(SkIntToScalar(N + 8), 0);
                }
            }

        virtual void onDrawContent(SkCanvas* canvas)
            {
            canvas->translate(SkIntToScalar(10), SkIntToScalar(10));

            canvas->scale(1.00000001f, 0.9999999f);

            drawN2(canvas, fBitmap);

            canvas->translate(0, SkIntToScalar(N + 8));
            SkBitmap bitmap(fBitmap);
            bitmap.buildMipMap();
            drawN2(canvas, bitmap);

            SkScalar time = SampleCode::GetAnimScalar(SkIntToScalar(1)/4,
                            SkIntToScalar(2));
            if (time >= SK_Scalar1)
                {
                time = SkIntToScalar(2) - time;
                }
            fWidth = 8 + SkScalarRound(N * time);

            SkRect dst;
            dst.set(0, 0, SkIntToScalar(fWidth), SkIntToScalar(fWidth));

            SkPaint paint;
            paint.setFilterBitmap(true);
            paint.setAntiAlias(true);

            canvas->translate(0, SkIntToScalar(N + 8));
            canvas->drawBitmapRect(fBitmap, NULL, dst, NULL);
            canvas->translate(SkIntToScalar(N + 8), 0);
            canvas->drawBitmapRect(fBitmap, NULL, dst, &paint);
            canvas->translate(-SkIntToScalar(N + 8), SkIntToScalar(N + 8));
            canvas->drawBitmapRect(bitmap, NULL, dst, NULL);
            canvas->translate(SkIntToScalar(N + 8), 0);
            canvas->drawBitmapRect(bitmap, NULL, dst, &paint);

            SkShader* s = SkShader::CreateBitmapShader(bitmap,
                          SkShader::kRepeat_TileMode,
                          SkShader::kRepeat_TileMode);
            paint.setShader(s)->unref();
            SkMatrix m;
            m.setScale(SkIntToScalar(fWidth) / N,
                       SkIntToScalar(fWidth) / N);
            s->setLocalMatrix(m);
            SkRect r;
            r.set(0, 0, SkIntToScalar(4*N), SkIntToScalar(5*N/2));
            r.offset(SkIntToScalar(N + 12), -SkIntToScalar(N + 4));
            canvas->drawRect(r, paint);

            this->inval(NULL);
            }

    private:
        int fWidth;

        typedef SampleView INHERITED;
    };

//////////////////////////////////////////////////////////////////////////////

static SkView* MyFactory()
    {
    return new MipMapView;
    }
static SkViewRegister reg(MyFactory);

